package com.michale.system.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.michale.common.constants.UserConstant;
import com.michale.common.domain.permissions.RoleEntity;
import com.michale.common.domain.permissions.UserEntity;
import com.michale.common.domain.permissions.UserPostEntity;
import com.michale.common.domain.permissions.UserRoleEntity;
import com.michale.common.domain.system.PostEntity;
import com.michale.common.exception.ServiceException;
import com.michale.common.utils.Date.DateUtils;
import com.michale.common.utils.Ip.IpUtils;
import com.michale.common.utils.Ip.ServletUtils;
import com.michale.common.utils.String.StringUtils;
import com.michale.common.utils.security.SecurityUtils;
import com.michale.system.mapper.permissions.UserMapper;
import com.michale.system.mapper.permissions.UserPostMapper;
import com.michale.system.mapper.permissions.UserRoleMapper;
import com.michale.system.service.PostService;
import com.michale.system.service.RoleService;
import com.michale.system.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Michale
 * @apiNote 用户管理 业务层
 */
@Slf4j
@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Resource
    private RoleService roleService;
    @Resource
    private PostService postService;
    @Resource
    private UserPostMapper userPostMapper;
    @Resource
    private UserRoleMapper userRoleMapper;

    /**
     * 根据条件分页查询用户列表
     *
     * @param userEntity 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<UserEntity> selectUserList(UserEntity userEntity) {
        return baseMapper.selectUserList(userEntity);
    }

    /**
     * 注册用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean registerUser(UserEntity user) {
        return baseMapper.insert(user) > 0;
    }

    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public UserEntity selectUserById(Long userId) {
        return baseMapper.selectUserById(userId);
    }

    /**
     * 根据用户ID查询用户所属角色组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserRoleGroup(String userName) {
        List<RoleEntity> list = roleService.selectRolesByUserName(userName);
        if (CollectionUtils.isEmpty(list)) {
            return StringUtils.EMPTY;
        }
        return list.stream().map(RoleEntity::getRoleName).collect(Collectors.joining(","));
    }

    /**
     * 根据用户名查询用户详细信息
     *
     * @param userName 账户名
     * @return 用户详细信息
     */
    @Override
    public UserEntity selectUserByUserName(String userName) {
        return baseMapper.selectUserByUserName(userName);
    }

    /**
     * 根据用户ID查询用户所属岗位组
     *
     * @param userName 用户名
     * @return 结果
     */
    @Override
    public String selectUserPostGroup(String userName) {
        List<PostEntity> list = postService.selectPostsByUserName(userName);
        if (CollectionUtils.isEmpty(list)) {
            return StringUtils.EMPTY;
        }
        return list.stream().map(PostEntity::getPostName).collect(Collectors.joining(","));
    }

    /**
     * 校验用户名称是否唯一
     *
     * @param userEntity 用户名称
     * @return 结果
     */
    @Override
    public String checkUserNameUnique(UserEntity userEntity) {
        long userId = StringUtils.isNull(userEntity.getUserId()) ? -1L : userEntity.getUserId();
        UserEntity info = baseMapper.checkPhoneUnique(userEntity.getUserName());
        if (StringUtils.isNotNull(info) && info.getUserId() != userId) {
            return UserConstant.NOT_UNIQUE;
        }
        return UserConstant.UNIQUE;
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param userEntity 用户信息
     * @return 结果
     */
    @Override
    public String checkPhoneUnique(UserEntity userEntity) {
        long userId = StringUtils.isNull(userEntity.getUserId()) ? -1L : userEntity.getUserId();
        UserEntity info = baseMapper.checkPhoneUnique(userEntity.getPhoneNumber());
        if (StringUtils.isNotNull(info) && info.getUserId() != userId) {
            return UserConstant.NOT_UNIQUE;
        }
        return UserConstant.UNIQUE;
    }

    /**
     * 校验email是否唯一
     *
     * @param userEntity 用户信息
     * @return 结果
     */
    @Override
    public String checkEmailUnique(UserEntity userEntity) {
        long userId = StringUtils.isNull(userEntity.getUserId()) ? -1L : userEntity.getUserId();
        UserEntity info = baseMapper.checkPhoneUnique(userEntity.getEmail());
        if (StringUtils.isNotNull(info) && info.getUserId() != userId) {
            return UserConstant.NOT_UNIQUE;
        }
        return UserConstant.UNIQUE;
    }

    /**
     * 修改用户密码
     *
     * @param userEntity 被操作者的信息
     */
    @Override
    public int restPossWord(UserEntity userEntity) {
        String password = userEntity.getPassword();
        String encryptPassword = SecurityUtils.encryptPassword(password);
        userEntity.setPassword(encryptPassword);
        userEntity.setUpdateBy(SecurityUtils.getUsername());
        return baseMapper.updateById(userEntity);
    }

    /**
     * 添加新用户
     *
     * @param userEntity 新用户信息
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int insertUser(UserEntity userEntity) {
        userEntity.setCreateBy(SecurityUtils.getUsername());
        userEntity.setPassword(SecurityUtils.encryptPassword(userEntity.getPassword()));
        // 新增用户岗位关联
        insertUserPost(userEntity.getUserId(), userEntity.getPostIds());
        //添加用户和角色的关系
        insertUserRole(userEntity.getUserId(), userEntity.getRoleIds());
        return baseMapper.insertUser(userEntity);
    }

    /**
     * 新增用户岗位关联
     *
     * @param userId  用户ID
     * @param postIds 岗位ID
     */
    private void insertUserPost(Long userId, Long[] postIds) {
        if (StringUtils.isNotEmpty(postIds)) {
            List<UserPostEntity> list = new ArrayList<>(postIds.length);
            for (Long postId : postIds) {
                UserPostEntity sysUserPostEntity = new UserPostEntity();
                sysUserPostEntity.setUserId(userId);
                sysUserPostEntity.setPostId(postId);
                list.add(sysUserPostEntity);
            }
            userPostMapper.batchUserPost(list);
        }

    }

    /**
     * 新增用户与角色管理
     *
     * @param userId  用户ID
     * @param roleIds 角色ID
     */
    private void insertUserRole(Long userId, Long[] roleIds) {
        if (StringUtils.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            List<UserRoleEntity> list = new ArrayList<>(roleIds.length);
            for (Long roleId : roleIds) {
                UserRoleEntity sysUserRoleEntity = new UserRoleEntity();
                sysUserRoleEntity.setRoleId(roleId);
                sysUserRoleEntity.setUserId(userId);
                list.add(sysUserRoleEntity);
            }
            userRoleMapper.batchUserRole(list);
        }
    }

    /**
     * 修改用户状态
     *
     * @param userEntity 修改用户参数
     */
    @Override
    public int changeStatus(UserEntity userEntity) {
        userEntity.setUpdateBy(SecurityUtils.getUsername());
        return baseMapper.updateUser(userEntity);
    }

    /**
     * 根据与用户ID查询角色信息
     *
     * @param userId 用户ID
     * @return 角色列表
     */
    @Override
    public List<RoleEntity> selectRoleByUserId(Long userId) {
        List<RoleEntity> sysRoleList = roleService.selectRoleByUserId(userId);
        List<RoleEntity> selectAllRole = roleService.selectAllRole();
        for (RoleEntity sysRole : selectAllRole) {
            for (RoleEntity userRole : sysRoleList) {
                if (sysRole.getRoleId().longValue() == userRole.getRoleId().longValue()) {
                    sysRole.setFlag(true);
                }
                break;
            }
        }
        return selectAllRole;
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    @Override
    public int deleteUserByIds(Long[] userIds) {
        for (Long userId : userIds) {
            checkUserAllowed(selectUserById(userId));
        }
        // 删除用户与角色关联
        int i = roleService.deleteUserRole(userIds);
        // 删除用户与岗位关联
        int i1 = postService.deleteUserPost(userIds);
        return baseMapper.deleteUserByIds(userIds);
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    @Override
    public void insertUserAuth(Long userId, Long[] roleIds) {
        userRoleMapper.deleteById(userId);
        if (StringUtils.isNotEmpty(roleIds)) {
            // 新增用户与角色管理
            List<UserRoleEntity> list = new ArrayList<>(roleIds.length);
            for (Long roleId : roleIds) {
                UserRoleEntity ur = new UserRoleEntity();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                list.add(ur);
            }
            userRoleMapper.batchUserRole(list);
        }
    }

    /**
     * 更新用户信息
     *
     * @param userEntity 用户信息
     * @return 结果
     */
    @Override
    public int updateUser(UserEntity userEntity) {
        userEntity.setUpdateBy(SecurityUtils.getUsername());
        // 删除用户与角色关联
        userRoleMapper.deleteUserRoleByUserId(userEntity.getUserId());
        // 新增用户与角色管理
        insertUserRole(userEntity.getUserId(), userEntity.getRoleIds());
        // 删除用户与岗位关联
        userPostMapper.deleteUserPostByUserId(userEntity.getUserId());
        // 新增用户与岗位管理
        insertUserPost(userEntity.getUserId(), userEntity.getPostIds());
        return baseMapper.updateById(userEntity);
    }

    /**
     * 修改用户基本信息
     *
     * @param userEntity 用户信息
     */
    @Override
    public int updateUserProfile(UserEntity userEntity) {
        return baseMapper.updateUser(userEntity);
    }

    /**
     * 修改用户头像
     *
     * @param userName 账户名
     * @param avatar   头像地址
     */
    @Override
    public int updateUserAvatar(String userName, String avatar) {
        return baseMapper.updateUserAvatar(userName, avatar);
    }

    /**
     * 根据条件分页查询已分配用户角色列表
     *
     * @param userEntity 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<UserEntity> selectAllocatedList(UserEntity userEntity) {
        return baseMapper.selectAllocatedList(userEntity);
    }

    /**
     * 查询未分配用户的角色列表
     *
     * @param userEntity 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<UserEntity> selectUnAllocatedList(UserEntity userEntity) {
        return baseMapper.selectUnallocatedList(userEntity);
    }

    /**
     * 校验用户是否有数据权限
     *
     * @param userId 用户id
     */
    @Override
    public void checkUserDataScope(Long userId) {
        if (!SecurityUtils.isAdmin(SecurityUtils.getUserIdentity())) {
            UserEntity user = new UserEntity();
            user.setUserId(userId);
            List<UserEntity> users = baseMapper.selectUserList(user);
            if (StringUtils.isEmpty(users)) {
                throw new ServiceException("没有权限访问用户数据！");
            }
        }
    }

    /**
     * 判断登录者是否具有身份标识
     *
     * @param userEntity   用户信息
     * @param userClass 用户类型 (loginUser:登录者 operateUser:被操作的用户)
     */
    @Override
    public void checkUserIdentity(UserEntity userEntity, String userClass) {
        if (userClass.equals(UserConstant.LOGIN_USER)) {
            if (StringUtils.isEmpty(userEntity.getIdentity())) {
                throw new ServiceException("判断登录者是否具有用户标识", "您的用户未分配身份标识");
            }
        } else if (userClass.equals(UserConstant.OPERATE_USER)) {
            if (StringUtils.isEmpty(userEntity.getIdentity()))
                throw new ServiceException("判断登录者是否具有用户标识", "操作的用户未分配身份标识");
        } else {
            throw new ServiceException("判断登录者是否具有用户标识", "无法识别的用户类型");
        }
    }

    /**
     * 检查用户是否允许操作
     *
     * @param userEntity 用户信息
     */
    @Override
    public void checkUserAllowed(UserEntity userEntity) {
        if (!SecurityUtils.getUserIdentity().equals(UserConstant.IS_ADMIN)) {
            checkUserIdentity(SecurityUtils.getLoginUser().getUserEntity(), UserConstant.LOGIN_USER);
            checkUserIdentity(userEntity, UserConstant.OPERATE_USER);
            int i = SecurityUtils.getUserIdentity().compareTo(userEntity.getIdentity());
            if (i == 0) {
                throw new ServiceException("检查用户是否允许操作", "不允许操作同级级管理员");
            }
            if (i > 0) {
                throw new ServiceException("检查用户是否允许操作", "不允许操作上级管理员");
            }
        }
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId) {
        UserEntity userEntity = new UserEntity();
        userEntity.setUserId(userId);
        userEntity.setLoginIp(IpUtils.getIpAddress(ServletUtils.getRequest()));
        userEntity.setLoginDate(DateUtils.getNowDate());
        updateUserProfile(userEntity);
    }
}
